<script setup>

import {onMounted, ref} from "vue";
import {httpGet, httpPost} from "@/utils/http.js";
import {ElMessage} from "element-plus";
import {dateFormat, processContent} from "@/utils/libs.js";
import {Search} from "@element-plus/icons-vue";
import 'highlight.js/styles/a11y-dark.css'
import hl from 'highlight.js'
// 用户提示词显示组件
import ChatPrompt from "@/components/ChatPrompt.vue";
// 显示模型回复消息组件
import ChatReply from "@/components/ChatReply.vue";
// mathjax3 插件：用于在 Markdown 中解析 LaTeX 数学公式
// 通过 md.use() 加载插件后，能自动将 $...$（行内公式）和 $$...$$（独立公式）转为 MathJax 兼容的 HTML 标签。
import mathjaxPlugin from 'markdown-it-mathjax3'
// 将 Markdown 解析为 HTML
import MarkDownIt from 'markdown-it'
import ClipboardJS from "clipboard";

// 变量定义
const data = ref({
  // 会话
  chat: {
    items: [],
    query: {title: '', created_at: [], page: 1, page_size: 15},
    total: 0,
    page: 1,
    pageSize: 15,
    loading: true
  },
  // 聊天消息
  message: {
    items: [],
    query: {title: '', created_at: [], page: 1, page_size: 15},
    total: 0,
    page: 1,
    pageSize: 15,
    loading: true
  }
})
// 默认激活的面板
const activeName = ref('chat')

onMounted(() => {
  fetchChatData()
})

// 卡片切换触发
const handleChange = (tab) => {
  if (tab === "chat") {
    fetchChatData()
  } else if (tab === "message") {
    fetchMessageData()
  }
}

// 会话搜索输入框触发事件
const searchChat = (evt) => {
  if (evt.keyCode === 13) {
    fetchChatData()
  }
}

// 消息搜索输入框触发事件
const searchMessage = (evt) => {
  if (evt.keyCode === 13) {
    fetchMessageData()
  }
}

// 查询会话列表
const fetchChatData = () => {
  const d = data.value.chat
  // 如果 user_id 为空就把这个属性删除掉，否则请求后端接口报错
  if(d.query['user_id'] === '') {
    delete d.query['user_id']
  }
  d.query.page = d.page
  d.query.page_size = d.pageSize
  d.loading = true
  httpPost('api/admin/chat/chat_list', d.query).then(res => {
    if (res.data) {
      d.items = res.data.items
      d.total = res.data.total
      d.page = res.data.page
      d.pageSize = res.data.page_size
    }
    d.loading = false
  }).catch(e => {
    d.loading = false
    ElMessage.error('查询会话数据列表失败：' + e.message)
  })
}

// 查询消息列表数据
const fetchMessageData = () => {
  const d = data.value.message
  // 如果 user_id 为空就把这个属性删除掉，否则请求后端接口报错
  if(d.query['user_id'] === '') {
    delete d.query['user_id']
  }
  d.query.page = d.page
  d.query.page_size = d.pageSize
  d.loading = true
  httpPost('api/admin/chat/messages_list', d.query).then(res => {
    if (res.data) {
      d.items = res.data.items
      d.total = res.data.total
      d.page = res.data.page
      d.pageSize = res.data.page_size
    }
    d.loading = false
  }).catch(e => {
    d.loading = false
    ElMessage.error('查询消息数据列表失败：' + e.message)
  })
}

// 删除会话
const removeChat = (row) => {
  httpGet('api/admin/chat/remove_chat?chat_id=' + row.chat_id).then(() => {
    ElMessage.success('删除成功！')
    fetchChatData()
  }).catch(e => {
    ElMessage.error('删除失败：' + e.message)
  })
}

// 删除消息
const removeMessage = (row) => {
  httpGet('api/admin/chat/remove_message?id=' + row.id).then(() => {
    ElMessage.success('删除成功！')
    fetchMessageData()
  }).catch(e => {
    ElMessage.error('删除失败：' + e.message)
  })
}

const md = new MarkDownIt({
  breaks: true, // 将换行符转换为 `<br>` 标签
  html: true, // 允许 Markdown 中嵌入 HTML 标签
  linkify: true, // 自动将 URL 文本转为超链接
  typographer: true, // 启用排版优化（如引号美化、连字符转换）
  // 代码高亮与复制功能
  // str: 表示代码块中的原始文本内容，即未经转义或高亮处理的纯代码字符串。
  // lang: 表示代码块指定的编程语言类型（如 js、python），通常由 Markdown 语法中的代码块标识符定义（如 ```js）。
  //        用于判断是否支持该语言的高亮。例如，hljs.getLanguage(lang) 会检查 highlight.js 是否内置了该语言的语法规则
  // 函数需返回包裹在 <pre><code> 标签中的高亮结果
  highlight: function (str, lang) {
    // lang 表示代码块支持的语言，hl.getLanguage(lang) 判断该语言是否支持高亮
    if (lang && hl.getLanguage(lang)) {
      // 处理代码高亮
      const preCode = hl.highlight(lang, str, true).value
      // 将代码包裹在 pre 中
      return `<pre class="code-container"><code class="language-${lang} hljs">${preCode}</code></pre>`
    }
    // 处理代码高亮
    const preCode = md.utils.escapeHtml(str)
    // 将代码包裹在 pre 中
    return `<pre class="code-container"><code class="language-${lang} hljs">${preCode}</code></pre>`
  }
})
md.use(mathjaxPlugin)

// 是否显示消息弹框
const showContentDialog = ref(false)
// 消息弹框显示的内容
const dialogContent = ref('')
// 点击消息时触发弹框
const showContent = (content) => {
  showContentDialog.value = true
  // md.render 将修剪后的 Markdown 文本转换为 HTML 字符串
  // processPrompt 对其进行 HTML 特殊字符转义
  // dialogContent.value = md.render(processContent(content))
  dialogContent.value = content
  console.log(dialogContent.value)
}


const showChatItemDialog = ref(false)
const messages = ref([])
// 查询会话聊天记录
const showMessages = (row) => {
  showChatItemDialog.value = true
  messages.value = []
  httpGet('api/admin/chat/history?chat_id=' + row.chat_id).then(res => {
    const data = res.data
    for (let i = 0; i < data.length; i++) {
      messages.value.push(data[i])
    }
  }).catch(e => {
    ElMessage.error('加载会话聊天记录失败：' + e.message)
  })
}

const clipboard = new ClipboardJS('.copy-reply, .copy-code-btn, .copy-prompt');
clipboard.on('success', () => {
  ElMessage.success('复制成功！');
})

clipboard.on('error', () => {
  ElMessage.error('复制失败！');
})

</script>

<template>
  <div class="container chat-page">
    <el-tabs v-model="activeName" @tab-change="handleChange">
      <el-tab-pane label="对话列表" name="chat" v-loading="data.chat.loading">
        <div class="handle-box">
          <el-input v-model.number="data.chat.query.user_id" placeholder="账户ID" class="handle-input mr10"
                    @keyup="searchChat($event)"></el-input>
          <el-input v-model="data.chat.query.title" placeholder="对话标题" class="handle-input mr10"
                    @keyup="searchChat($event)"></el-input>
          <el-date-picker
              v-model="data.chat.query.created_at"
              type="daterange"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
              style="margin-right: 10px;width: 200px; position: relative;top:3px;"
          />
          <el-button type="primary" :icon="Search" @click="fetchChatData">搜索</el-button>
        </div>
        <el-row>
          <el-table :data="data.chat.items" :row-key="row => row.id" table-layout="auto">
            <el-table-column prop="user_id" label="账户ID"/>
            <el-table-column prop="username" label="账户"/>
            <el-table-column label="图标">
              <template #default="scope">
                <el-avatar :size="30" :src="scope.row.role.icon"/>
              </template>
            </el-table-column>
            <el-table-column label="角色">
              <template #default="scope">
                <span>{{ scope.row.role.name }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="model" label="模型"/>
            <el-table-column prop="title" label="标题"/>
            <el-table-column prop="msg_num" label="消息数量"/>
            <el-table-column prop="token" label="消耗算力"/>
            <el-table-column label="创建时间">
              <template #default="scope">
                <span>{{ dateFormat(scope.row['created_at']) }}</span>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="180">
              <template #default="scope">
                <el-button size="small" type="primary" @click="showMessages(scope.row)">查看</el-button>
                <el-popconfirm title="确定要删除当前记录吗？" @confirm="removeChat(scope.row)">
                  <template #reference>
                    <el-button size="small" type="danger">删除</el-button>
                  </template>
                </el-popconfirm>
              </template>
            </el-table-column>
          </el-table>
        </el-row>
        <div class="pagination">
          <el-pagination
              v-if="data.chat.total > 0" background
              layout="total, prev, pager, next"
              v-model:current-page="data.chat.page"
              v-model:page-size="data.chat.pageSize"
              @current-change="fetchChatData()"
              :total="data.chat.total"
          />
        </div>
      </el-tab-pane>
      <el-tab-pane label="消息记录" name="message">
        <div class="handle-box">
          <el-input v-model.number="data.message.query.user_id" placeholder="账户ID" class="handle-input mr10"
                    @keyup="searchMessage($event)"/>
          <el-input v-model="data.message.query.content" placeholder="消息内容" class="handle-input mr10"
                    @keyup="searchMessage($event)"/>
          <el-input v-model="data.message.query.model" placeholder="模型" class="handle-input mr10"
                    @keyup="searchMessage($event)"/>
          <el-date-picker
              v-model="data.message.query.created_at"
              type="daterange"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
              style="margin-right: 10px;width: 200px; position: relative;top:3px;"
          />
          <el-button type="primary" :icon="Search" @click="fetchMessageData">搜索</el-button>
        </div>
        <el-row>
          <el-table :data="data.message.items" :row-key="row => row.id" table-layout="auto">
            <el-table-column prop="user_id" label="账户ID"/>
            <el-table-column prop="username" label="账户"/>
            <el-table-column label="角色">
              <template #default="scope">
                <el-avatar :size="30" :src="scope.row.icon"/>
              </template>
            </el-table-column>
            <el-table-column prop="model" label="模型"/>
            <el-table-column label="消息内容">
              <template #default="scope">
                <el-text style="width: 200px" truncated @click="showContent(scope.row)">
                  {{ scope.row.content }}
                </el-text>
              </template>
            </el-table-column>
            <el-table-column prop="type" label="消息类型"/>
            <el-table-column prop="tokens" label="算力"/>
            <el-table-column label="创建时间">
              <template #default="scope">
                <span>{{ dateFormat(scope.row['created_at']) }}</span>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="180">
              <template #default="scope">
                <el-button size="small" type="primary" @click="showContent(scope.row)">查看</el-button>
                <el-popconfirm title="确定要删除当前记录吗？" @confirm="removeMessage(scope.row)">
                  <template #reference>
                    <el-button size="small" type="danger">删除</el-button>
                  </template>
                </el-popconfirm>
              </template>
            </el-table-column>
          </el-table>
        </el-row>
        <div class="pagination">
          <el-pagination
              v-if="data.message.total > 0" background
              layout="total, prev, pager, next"
              v-model:current-page="data.message.page"
              v-model:page-size="data.message.pageSize"
              @current-change="fetchMessageData()"
              :total="data.message.total"
          />
        </div>
      </el-tab-pane>
    </el-tabs>
    <!--  消息弹框  -->
    <el-dialog v-model="showContentDialog" title="消息详情" class="chat-dialog" style="--el-dialog-width:60%">
      <div class="chat-box chat-page">
        <chat-prompt v-if="dialogContent.type === 'prompt'" :data="dialogContent" />
        <chat-reply  v-else-if="dialogContent.type === 'reply'" :read-only="true" :data="dialogContent" />
      </div>
    </el-dialog>
    <!--  会话弹框  -->
    <el-dialog v-model="showChatItemDialog" title="对话详情" class="chat-dialog" style="--el-dialog-width:60%">
      <div class="chat-box chat-page">
        <div v-for="item in messages" :key="item.id">
          <chat-prompt list-style="chat" v-if="item.type === 'prompt'" :data="item" />
          <chat-reply  list-style="chat" v-else-if="item.type === 'reply'" :read-only="true" :data="item" />
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<style scoped lang="stylus">
.chat-page {
  .handle-box {
    margin-bottom 20px

    .handle-input {
      max-width 150px;
      margin-right 10px;
    }
  }

  .opt-box {
    padding-bottom: 10px;
    display flex;
    justify-content flex-end

    .el-icon {
      margin-right: 5px;
    }
  }

  .el-select {
    width: 100%
  }

  .pagination {
    padding 20px
    display flex
    justify-content right
  }

  .chat-detail {
    max-height 90vh
    overflow auto
  }

  .chat-box {
    overflow auto

    // 变量定义
    --content-font-size: 16px;
    --content-color: #c1c1c1;

    font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
    max-height 90vh

    .chat-line {
      // 隐藏滚动条

      ::-webkit-scrollbar {
        width: 0;
        height: 0;
        background-color: transparent;
      }

      font-size: 14px;
      display: flex;
      align-items: flex-start;

    }
  }

}
</style>